// 第三方或自己封装的一些功能组件
import { useSelector } from 'react-redux'
import { Button, Form, Input, Select } from 'antd'
import GlobalUpload from '@/commponents/common/GlobalUpload'
// 下面的是类型声明
import { ReactChild } from 'react'
// 第三方或自己写的声明
import { IProductState } from '@/types/product'
import { IOptions } from '@/types/global'
import { Callbacks } from 'rc-field-form/lib/interface'

/**
 * 约束props的内容
 * callbacks是antd使用的表单域插件提供的声明，直接引用即可
 * children 来自于react
 */
interface IProps extends Callbacks {
  children: ReactChild
  imagesMax?: number
}

/**
 * 约束从store中返回的数据
 * 这是当前组件仅有的两个数据
 */
interface IState {
  category: IOptions[]
  freight: IOptions[]
}

/**
 * 添加商品的表单部分，这部分只进行UI展示，所有的交互与数据，都由父组件进行管理
 * 要注意的是form中的几个方法，使用了rc-field-form提供的类型声明
 * children，使用的是react自己提供的ReactChildren声明
 */
export default function AddProductMain(props: IProps) {
  const [form] = Form.useForm()

  // 从redux中获取状态的方法
  // useSelector接受的泛型参数有两个
  // 第一个参数是store返回的类型，这个参数可以使用any定义，如果有公用的类型声明也可以稍稍约束一下
  // 第二个参数是我们计算后返回的值的类型，这个一定要有，否则我们在使用返回值时可能会出现各种问题
  const { category, freight } = useSelector<
    { productInfo: IProductState },
    IState
  >(state => ({
    category: state.productInfo.productCategory.map(item => ({
      label: item.cate_name,
      value: item.id,
    })),
    freight: state.productInfo.templateList.map(item => ({
      label: item.name,
      value: item.id,
    })),
  }))
  return (
    <div className="add-first-form-wrap">
      <Form
        form={form}
        onFinish={props.onFinish}
        onFinishFailed={props.onFinishFailed}
        onValuesChange={props.onValuesChange}
      >
        {/* 商品名称 */}
        <Form.Item
          name="store_name"
          label="商品名称"
          rules={[{ required: true, message: '请输入商品名称' }]}
        >
          <Input className="half" />
        </Form.Item>
        {/* 分类下拉 */}
        <Form.Item
          name="category"
          label="商品分类"
          rules={[{ required: true, message: '请选择商品分类' }]}
        >
          <Select
            className="half"
            // select的options也可以使用这种方式传入，会更加容易渲染
            options={category}
            placeholder="请选择商品分类"
          />
        </Form.Item>
        {/* 单位名称 */}
        <Form.Item
          name="unit_name"
          label="单位"
          rules={[{ required: true, message: '请填写单位名称' }]}
        >
          <Input className="half" />
        </Form.Item>
        {/* 上传封面图片 */}
        <Form.Item
          name="image"
          label="商品封面"
          rules={[{ required: true, message: '请上传商品封面图片' }]}
        >
          <GlobalUpload />
        </Form.Item>
        {/* 上传轮播图列表 */}
        <Form.Item
          name="slider_image"
          label={
            <div className="multiple-line">
              <p className="title">商品轮播图</p>
              <p className="sub-title">(最多{props.imagesMax}张)</p>
            </div>
          }
          rules={[{ required: true, message: '请上传商品轮播图' }]}
        >
          <GlobalUpload maxCount={props.imagesMax} />
        </Form.Item>

        {/* 商品规格选择 因此处逻辑较复杂 包含规格选择、规格输入、规格表单、规格列表等相
            关组件，为了避免单个文件逻辑太过复杂，这里由由父组件确认具体渲染什么内容 */}
        {props.children}

        {/* 运费模板 */}
        <Form.Item
          name="freight"
          label="运费模板"
          rules={[{ required: true, message: '请选择运费模板' }]}
        >
          <Select
            className="half"
            options={freight}
            placeholder="请选择运费模板"
          />
        </Form.Item>
        {/* 提交按钮，激活onFinish事件 */}
        <Form.Item>
          <Button type="primary" htmlType="submit">
            下一步
          </Button>
        </Form.Item>
      </Form>
    </div>
  )
}
